package com.darwin.darwinDisplay
{
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.MovieClip;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;
	

	/**
	 * Darwin动画管理器
	 * 保存项目中所有用到的darwin素材文件
	 * @author jasonwluck,Roland
	 * 
	 */	
	public class DarBitmapManager
	{
		private static var _instance:DarBitmapManager;
		/**
		 *  所有绘制完成的动画序列,序列的索引为源对象本身,可能是DarBitmapData或Class对象
		 */
		private var _framesDic:Dictionary;
		/**
		 *  和framesDic相对应的镜像字典,保存所有动画序列的镜像序列,索引为源对象本身,可能是DarBitmapData或Class对象
		 */
		private var _mirrorFramesDic:Dictionary;
		/**
		 *	 资源引用计数,当计数为0时,则将在经过保留时间之后彻底销毁对应动画序列
		 */
		private var _totalDic:Dictionary;
		/**
		 *	动画偏移点字典 
		 */
		private var _offsetPointDic:Dictionary;

		/**
		 *	动画帧偏移字典 
		 */
		private var _framesOffsetListDic:Dictionary;

		/**
		 *	 最大线程数
		 */
		public static var MAX_LOADER:int = 10;
		
		/**
		 *	资源失去所有引用后的保留时间，超过此时间如果没有新的引用则将销毁其对应的动画序列 (毫秒)
		 */
		public static const DESTROY_DELAY_TIME:int = 2000;
		
		private var timeOutId:uint = 0;

		
		public function DarBitmapManager()
		{
			if(_instance)
			{
				throw new Error("实例化单例DarwinBitmapManager出错");
			}else
			{
				//all
				_framesDic = new Dictionary();
				_framesOffsetListDic = new Dictionary();
				_offsetPointDic = new Dictionary();
				_totalDic= new Dictionary();
				//mirror
				_mirrorFramesDic = new Dictionary();
				
				//class
				_classCompFnDic = new Dictionary();
				_classDrawingNum = 0;
				//dar
				_darwinDic =  new Dictionary();
				_darwinBitmapMovieClipFuncDic = new Dictionary();
				_darwinBitmapMovieClipDic = new Dictionary();


			}
		}
		
		public static function getInstance():DarBitmapManager
		{
			if(_instance == null)
			{
				_instance = new DarBitmapManager();
			}
			return _instance;
		}
		//////////////////////////////////////////////
		//
		//   绘制class部分
		//
		///////////////////////////////////////////////
		private var _classCompFnDic:Dictionary;
		private var _classDrawingNum:int;//正在绘制的Class类型源的数量
		
		/**
		 *	根据传入类绘制动画序列
		 * @param source 要绘制的类
		 * @param compFn 完全绘制完成后的回调函数 格式function compFn(bitmapDataArray:Array,offsetPoint:Point,framesOffsetList:Array = null):void{}
		 * 							 其中参数bitmapDataArray为绘制完成的位图序列
		 */
		public function drawClass(source:Class,compFn:Function):void
		{
			if(source == null) return;
			if(_classCompFnDic[source] == null)
			{
				_classCompFnDic[source] = compFn;
			}
			if(_classDrawingNum < MAX_LOADER)
			{
				_classDrawingNum++;
				drawClassHandler(source);
			}else{
				setTimeout(drawClass,1,compFn);
			}
			
		}
		
		private function drawClassHandler(source:Class):void
		{
			if(_framesDic[source] == null)
			{
				_framesDic[source] = [];
				var $displayObject:DisplayObject = new source();
				var $rect:Rectangle;
				var $offsetPoint:Point;
				var $result:Object;
				if($displayObject is MovieClip)
				{//如果是MovieClip，则将它每一帧进行绘制
					var $mc:MovieClip = ($displayObject as MovieClip);
					var $total:int = getTotalFrame($mc,$mc.totalFrames);//$mc.totalFrames;
					$rect = getMovieClipBounds($mc,$total);
					$result = drawMovieClip($mc,$total,$rect);
				}else{
					$rect = getDisplayObjectBounds($displayObject);
					$result = drawDisplayObject($displayObject,$rect);
				}
				$offsetPoint = new Point($rect.x,$rect.y);
				_framesDic[source]= $result.frames;
				_offsetPointDic[source] = $offsetPoint;
				_framesOffsetListDic[source] = $result.offsets;
			}
			drawClassCompHandler(source);
		}
		
		
		private function drawClassCompHandler(source:Class):void
		{
			var compFn:Function = _classCompFnDic[source];
			var frames:Array = _framesDic[source];
			var framesOffsetList:Array = _framesOffsetListDic[source];
			var offset:Point = _offsetPointDic[source];
			if(compFn != null && frames !=null && offset)
			{
				compFn(frames,offset,framesOffsetList);
			}
			delete _classCompFnDic[source];
			_classDrawingNum--;
		}
		
		private function drawMovieClip(clip:MovieClip,totalFrame:int,rect:Rectangle):Object
		{
			var frames:Array = [];
			var offsetRectList:Array = [];
			var total:int = totalFrame;
			var r:Rectangle = rect;
			for (var i:int = 1; i <= total; i++)
			{
				clip.gotoAndStop(i)
				makeAllChildrenGoToFrame(clip, i);
				var bitmapData:BitmapData = new BitmapData(r.width, r.height, true, 0x00000000);
				var m:Matrix = new Matrix();
				m.translate(-r.x, -r.y);
				m.scale(clip.scaleX, clip.scaleY);
				bitmapData.draw(clip,m);
				
				var offsetRect:Rectangle = bitmapData.getColorBoundsRect(0xff000000,0,false);
				//留出透明边距
				offsetRect.x = offsetRect.x - DarBitmapMovieNode.transMargins;
				offsetRect.y = offsetRect.y - DarBitmapMovieNode.transMargins;
				offsetRect.width = offsetRect.width + DarBitmapMovieNode.transMargins*2;
				offsetRect.height = offsetRect.height + DarBitmapMovieNode.transMargins*2;
				//如果是空帧，申请一个高宽各为1的位图
				if(offsetRect.width==0)offsetRect.width = 1;
				if(offsetRect.height==0)offsetRect.height = 1;
				
				var frameBitmapData:BitmapData = new BitmapData(offsetRect.width,offsetRect.height,true,0);
				frameBitmapData.copyPixels(bitmapData,offsetRect,new Point()); 
				frames.push(frameBitmapData);
				
				offsetRectList.push(offsetRect);
			}
			return {"frames":frames,"offsets":offsetRectList};
		}
		
		/**
		 * draw出bitmapdata
		 * @param displayObject 需要draw的对象
		 * @return bitmapdata的列表
		 */
		private function drawDisplayObject(displayObject:DisplayObject,rect:Rectangle):Object
		{
			var bitmapData:BitmapData = new BitmapData(rect.width,rect.height,true,0x00000000);
			bitmapData.draw(displayObject,new Matrix(1,0,0,1,-Math.floor(rect.x),-Math.floor(rect.y)));
			var offsetRect:Rectangle = bitmapData.getColorBoundsRect(0xff000000,0,false);
			offsetRect.x = offsetRect.x - DarBitmapMovieNode.transMargins;
			offsetRect.y = offsetRect.y - DarBitmapMovieNode.transMargins;
			offsetRect.width = offsetRect.width + DarBitmapMovieNode.transMargins*2;
			offsetRect.height = offsetRect.height + DarBitmapMovieNode.transMargins*2;
			//如果是空帧，申请一个高宽各为1的位图
			if(offsetRect.width==0)offsetRect.width = 1;
			if(offsetRect.height==0)offsetRect.height = 1;
			var frameBitmapData:BitmapData = new BitmapData(offsetRect.width,offsetRect.height,true,0);
			frameBitmapData.copyPixels(bitmapData,offsetRect,new Point()); 
			
			return {"frames":[frameBitmapData],"offsets":[offsetRect]};
		}

		private function getDisplayObjectBounds(displayObject:DisplayObject):Rectangle
		{
			var $rect:Rectangle;
			if (displayObject.hasOwnProperty("e_bounds") && displayObject["e_bounds"] != null)
			{
				var $e_bounds:DisplayObject = displayObject["e_bounds"];
				$rect = new Rectangle($e_bounds.x, $e_bounds.y, $e_bounds.width, $e_bounds.height);
				displayObject["e_bounds"].visible = false;
			} else {
				$rect = displayObject.getBounds(displayObject)
			}
			$rect.width = $rect.width?$rect.width:1;
			$rect.height = $rect.height?$rect.height:1;
			return $rect;
		}
		
		private function getMovieClipBounds(clip:MovieClip,totalFrame:int):Rectangle
		{
			var total:int = totalFrame;
			var maxRect:Rectangle = new Rectangle();
			for (var i:int = 1; i <= total; i++)
			{
				clip.gotoAndStop(i)
				makeAllChildrenGoToFrame(clip, i);
				var cR:Rectangle = getDisplayObjectBounds(clip);
				maxRect = maxRect.union(cR);
			}
			return maxRect;
		}
		
		private function getTotalFrame(m:*,total:int=1):int
		{
			if(m is DisplayObjectContainer)
			{
				for (var i:int = 0; i < m.numChildren; i++) {
					var c:* = m.getChildAt(i);
					if (c is MovieClip) {
						 if(total < c.totalFrames)
						 {
							 total = c.totalFrames;
						 }
					}
					getTotalFrame(c,total);
				}
			}
			return total;
		}
		
		private function makeAllChildrenGoToFrame(m:*, f:int):void
		{
			if(m is DisplayObjectContainer)
			{
				for (var i:int = 0; i < m.numChildren; i++) {
					var c:* = m.getChildAt(i);
					makeAllChildrenGoToFrame(c, f);
					if (c is MovieClip) {
						c.gotoAndStop(f);
					}
				}
			}
		}
		//////////////////////////////////////////////
		//
		//   绘制dar部分
		//
		///////////////////////////////////////////////
		/**
		 * 保存解析后的darwin素材 
		 */		
		private var _darwinDic:Dictionary;
		/**
		 * 当前正在加载数据的darBitmapMovieClip数量 
		 */		
		private var _darwinBitmapMovieClipCount:int;
		/**
		 * 当前等待加载数据的darBitmapMovieClip 
		 */		
		private var _darwinBitmapMovieClipFuncDic:Dictionary;
		private var _darwinBitmapMovieClipDic:Dictionary;
		/**
		 * 根据dar绘制动画 将源数据保存在管理器中 
		 * @param source DarBitmapData
		 * @param compFn 开始初始化darBitmapMovieClip动画
		 */		
		public function drawDar(source:DarBitmapData,compFn:Function):void
		{

			if(_darwinBitmapMovieClipCount > MAX_LOADER)//超过线程上限，等待
			{
				_darwinBitmapMovieClipFuncDic[compFn] = compFn;
				_darwinBitmapMovieClipDic[compFn] = source;
			}else if(_darwinDic[source] && _framesDic[source]==null)//已经请求绘制但尚未绘制完成的，等待
			{
				_darwinBitmapMovieClipFuncDic[compFn] = compFn;
				_darwinBitmapMovieClipDic[compFn] = source;
			}else
			{
				if(!_darwinDic[source])
				{
					_darwinDic[source] = source;
				}
				_darwinBitmapMovieClipCount ++;
				
				if(_darwinBitmapMovieClipFuncDic[compFn])
				{
					delete _darwinBitmapMovieClipFuncDic[compFn];
					delete _darwinBitmapMovieClipDic[compFn];
				}
				compFn(_framesDic[source],_offsetPointDic[source],_framesOffsetListDic[source]);
			}
		}
		
		/**
		 *	 当一个darBitmapMovieClip加载完成 计数减一 
		 * @param source 加载完成的源对象
		 * @param frames 加载完成的位图帧序列
		 * 
		 */
		public function darBitmapMovieClipComplete(source:*,frames:Array,offsetPoint:Point,framesOffsetList:Array):void
		{
			_framesDic[source] = frames;
			_offsetPointDic[source] = offsetPoint;
			_framesOffsetListDic[source] = framesOffsetList;
			if(_darwinBitmapMovieClipCount <= MAX_LOADER)
			{
				for(var i:* in _darwinBitmapMovieClipFuncDic)
				{
					drawDar(_darwinBitmapMovieClipDic[i],_darwinBitmapMovieClipFuncDic[i]);
				}
			}
			_darwinBitmapMovieClipCount --;
		}
		
		//////////////////////////////////////////////
		//
		//   绘制镜像部分
		//
		///////////////////////////////////////////////
		/**
		 *	为传入的源绘制镜像帧,如果此源数据已经绘制过镜像则会立即返回
		 * @param source 源，作为保存镜像的键值
		 * @param frameList 已经绘制完成的位图帧序列
		 * @param isMirror 传入的位图序列是否已经为镜像,如果是,则直接镜像所对应的原始位图序列
		 * @return 镜像帧序列
		 */
		public function drawMirror(source:*,frameList:Array,isMirror:Boolean):Array
		{
			var $mirrorFrames:Array;
			if(_mirrorFramesDic[source] == null)
			{
				$mirrorFrames = [];
				for (var i:int = 0; i < frameList.length; i++) 
				{
					var $bitmapData:BitmapData = frameList[i];
					var $m:Matrix = new Matrix();
					$m.scale(-1,1);
					$m.translate($bitmapData.width,0);
					var $mirror:BitmapData = new BitmapData($bitmapData.width,$bitmapData.height,true,0);
					$mirror.draw($bitmapData,$m);
					$mirrorFrames.push($mirror);
				}
				_mirrorFramesDic[source] = $mirrorFrames;
			}else{
				if(isMirror)//已经为镜像,返回原始序列
				{
					$mirrorFrames = _framesDic[source];
				}else{
					$mirrorFrames = _mirrorFramesDic[source];
				}
			}
			return $mirrorFrames;
		}
		
		
		//////////////////////////////////////////////
		//
		//   资源管理部分
		//
		///////////////////////////////////////////////
		
		/**
		 *	对资源增加一次引用 
		 * @param source
		 * 
		 */
		public function addQuote(source:*):void
		{
			if(_totalDic[source] == null)
			{
				_totalDic[source] = 1;
			}else{
				_totalDic[source] += 1;
			}
		}
		
		/**
		 * 销毁位图动画资源 
		 * @param source
		 * 
		 */		
		public function destroy(source:*):void
		{
			//引用计数减一延时检查
			if(source != null)
			{
				_totalDic[source] -= 1;
				clearTimeout(timeOutId);
				timeOutId = setTimeout(delayDestroy,DESTROY_DELAY_TIME,source);
			}
		}
		
		
		/**
		 *	检查并处理资源需要延迟销毁的部分 
		 * @param source
		 * 
		 */
		private function delayDestroy(source:*):void
		{
			var total:int = _totalDic[source];
//			trace(source,"-->引用计数:",total);
			if(total<=0)
			{
				delete _darwinDic[source];
				delete _classCompFnDic[source];
				//删除引用计数
				delete _totalDic[source];
				//销毁帧序列,偏移点及其镜像
				delete _framesDic[source];
				delete _mirrorFramesDic[source];
				delete _offsetPointDic[source];
			}
		}
	}
}
